﻿using System;
using System.ComponentModel;
using System.IO.Ports;
using System.Windows.Forms;
using Oxage.Midi;

namespace Oxage.Forms
{
	public partial class SerialPortForm : UserControl, IConfigPanel
	{
		#region Constructor
		public SerialPortForm()
		{
			InitializeComponent();
			LoadComboBoxes();
		}
		#endregion

		#region Properties
		public bool IsLocked
		{
			set
			{
				this.Enabled = !value;
			}
		}

		public string PortName
		{
			get
			{
				return cmbPortName.Text;
			}
			set
			{
				cmbPortName.Text = value;
				foreach (var item in cmbPortName.Items)
				{
					if (item.ToString() == value.ToString())
					{
						cmbPortName.SelectedItem = item;
						break;
					}
				}
			}
		}

		public int BaudRate
		{
			get
			{
				int result = 0;
				int.TryParse(cmbBaudRate.Text, out result);
				return result;
			}
			set
			{
				cmbBaudRate.Text = value.ToString();
				foreach (var item in cmbBaudRate.Items)
				{
					if (item.ToString() == value.ToString())
					{
						cmbBaudRate.SelectedItem = item;
						break;
					}
				}
			}
		}

		public int DataBits
		{
			get
			{
				int result = 0;
				int.TryParse(cmbDataBits.Text, out result);
				return result;
			}
			set
			{
				cmbDataBits.Text = value.ToString();
				foreach (var item in cmbDataBits.Items)
				{
					if (item.ToString() == value.ToString())
					{
						cmbDataBits.SelectedItem = item;
						break;
					}
				}
			}
		}

		public Parity Parity
		{
			get
			{
				return (Parity)Enum.Parse(typeof(Parity), cmbParity.Text);
			}
			set
			{
				cmbParity.Text = value.ToString();
				foreach (var item in cmbParity.Items)
				{
					if (item.ToString() == value.ToString())
					{
						cmbParity.SelectedItem = item;
						break;
					}
				}
			}
		}

		public StopBits StopBits
		{
			get
			{
				return (StopBits)Enum.Parse(typeof(StopBits), cmbStopBits.Text);
			}
			set
			{
				cmbStopBits.Text = value.ToString();
				foreach (var item in cmbStopBits.Items)
				{
					if (item.ToString() == value.ToString())
					{
						cmbStopBits.SelectedItem = item;
						break;
					}
				}
			}
		}

		public Handshake Handshake
		{
			get
			{
				//return (Handshake)Enum.Parse(typeof(Handshake), cmbHandshake.Text);
				switch (cmbHandshake.SelectedIndex)
				{
					default:
					case 0:
						return Handshake.None;

					case 1:
						return Handshake.XOnXOff;

					case 2:
						return Handshake.RequestToSend;
				}
			}
			set
			{
				switch (value)
				{
					default:
					case Handshake.None:
						cmbHandshake.SelectedIndex = 0;
						break;

					case Handshake.XOnXOff:
						cmbHandshake.SelectedIndex = 1;
						break;

					case Handshake.RequestToSend:
						cmbHandshake.SelectedIndex = 2;
						break;
				}
			}
		}
		#endregion

		#region Methods
		protected void LoadComboBoxes()
		{
			//Serial port setup
			cmbPortName.Items.Clear();
			string[] portNames = SerialPort.GetPortNames();
			if (portNames != null && portNames.Length > 0)
			{
				foreach (string s in portNames)
				{
					cmbPortName.Items.Add(s);
				}
				cmbPortName.SelectedIndex = 0;
			}
			else
			{
				this.IsLocked = true;
				cmbPortName.Text = "(no ports)";
			}

			cmbParity.Items.Clear();
			cmbParity.Items.AddRange(Enum.GetNames(typeof(Parity)));
			cmbParity.SelectedIndex = 0;

			cmbStopBits.Items.Clear();
			cmbStopBits.Items.AddRange(Enum.GetNames(typeof(StopBits)));
			cmbStopBits.SelectedIndex = 1;

			cmbBaudRate.SelectedIndex = 7; //38400
			cmbDataBits.SelectedIndex = 3; //8
			cmbHandshake.SelectedIndex = 0; //None
		}
		#endregion

		#region Event handlers
		private void cmbBaudRate_Validating(object sender, CancelEventArgs e)
		{
			int x;
			e.Cancel = !int.TryParse(cmbBaudRate.Text, out x);
		}

		private void cmbDataBits_Validating(object sender, CancelEventArgs e)
		{
			int x;
			e.Cancel = !int.TryParse(cmbDataBits.Text, out x) || x < 5 || x > 8;
		}
		#endregion

		#region IConfigPanel Members
		public void SetProfile(Profile profile)
		{
			if (profile != null)
			{
				LoadComboBoxes();

				if (cmbPortName.Items.Count > 0)
				{
					cmbPortName.SelectedIndex = 0;
					string portName = profile["PortName"];
					if (portName != null)
					{
						int portNamesCount = cmbPortName.Items.Count;
						for (int i = 0; i < portNamesCount; i++)
						{
							if (cmbPortName.Items[i].ToString().ToUpper() == portName.ToUpper())
							{
								cmbPortName.SelectedIndex = i;
								break;
							}
						}
					}
				}

				int baudRate = 0;
				if (int.TryParse(profile["BaudRate"], out baudRate))
				{
					this.BaudRate = baudRate;
				}
				else
				{
					this.BaudRate = 38400;
				}

				int dataBits = 0;
				if (int.TryParse(profile["DataBits"], out dataBits))
				{
					this.DataBits = dataBits;
				}
				else
				{
					this.DataBits = 8;
				}

				if (profile["StopBits"] != null && Enum.IsDefined(typeof(StopBits), profile["StopBits"]))
				{
					this.StopBits = (StopBits)Enum.Parse(typeof(StopBits), profile["StopBits"]);
				}
				else
				{
					this.StopBits = StopBits.One;
				}

				if (profile["Parity"] != null && Enum.IsDefined(typeof(Parity), profile["Parity"]))
				{
					this.Parity = (Parity)Enum.Parse(typeof(Parity), profile["Parity"]);
				}
				else
				{
					this.Parity = Parity.None;
				}

				if (profile["Handshake"] != null && Enum.IsDefined(typeof(Handshake), profile["Handshake"]))
				{
					this.Handshake = (Handshake)Enum.Parse(typeof(Handshake), profile["Handshake"]);
				}
				else
				{
					this.Handshake = Handshake.None;
				}
			}
		}

		public Profile GetProfile()
		{
			Profile profile = new Profile();
			profile["PortName"] = this.PortName;
			profile["BaudRate"] = this.BaudRate.ToString();
			profile["DataBits"] = this.DataBits.ToString();
			profile["StopBits"] = this.StopBits.ToString();
			profile["Parity"] = this.Parity.ToString();
			profile["Handshake"] = this.Handshake.ToString();
			return profile;
		}

		public UserControl GetUserControl()
		{
			return this;
		}
		#endregion
	}
}
